/**
 * @fileOverview koni edge
 * @author huangtonger@aliyun.com
 */
const Koni = require('../../koni');
const Util = require('../../util/');
const { vec2 } = Util;

function getCirclePath(node, index) {
  const box = node.getBBox();
  const c = [ box.centerX, box.centerY ];
  const r = box.width / 2;
  const sd = 50;
  const dc = sd * (index + 1) + 50;
  const p1 = [ c[0] - r / 2, c[1] - Math.sqrt(3) / 2 * r ];
  const vc1 = [ p1[0] - c[0], p1[1] - c[1] ];
  const vc2 = vec2.scale([], vc1, (r + dc) / r);
  const p2 = [ c[0] + vc2[0], c[1] + vc2[1] ];
  const p3 = [ c[0] + r / 2, c[1] - Math.sqrt(3) / 2 * r ];
  const vc3 = [ p3[0] - c[0], p3[1] - c[1] ];
  const vc4 = vec2.scale([], vc3, (r + dc) / r);
  const p4 = [ c[0] + vc4[0], c[1] + vc4[1] ];
  return [
    [ 'M', p1[0], p1[1] ],
    // [ 'L', c[0], c[1] ]
    [ 'C', p2[0], p2[1], p4[0], p4[1], p3[0], p3[1] ]
  ];
}

function getParallelPath(source, target, index) {
  const sourceBox = source.getBBox();
  const targetBox = target.getBBox();
  const start = {
    x: sourceBox.centerX,
    y: sourceBox.centerY
  };
  const end = {
    x: targetBox.centerX,
    y: targetBox.centerY
  };
  const offset = 20 * (index + 1); // 向量方向长度系数
  const v1 = [ (end.x + start.x) * 0.5 - start.x, (end.y + start.y) * 0.5 - start.y ];
  const v2 = [ -v1[1], v1[0] ];
  const v2l = vec2.length(v2);
  vec2.scale(v2, v2, offset / v2l);
  // 控制点
  const cp = {
    x: v1[0] + v2[0] + start.x,
    y: v1[1] + v2[1] + start.y
  };
  const sp = source.getLinkPoints(cp)[0];
  const tp = target.getLinkPoints(cp)[0];
  return [
    [ 'M', sp.x, sp.y ],
    [ 'Q', cp.x, cp.y, tp.x, tp.y ]
  ];
}

Koni.registerEdge('koni-base', {
  getDefaultLabelRectPadding() {
    return Util.toAllPadding([ 0, 2 ]);
  },
  getPathByPoints({ points, source, target, item }) {
    if (source && target) {
      const parallelEdgesReverse = Util.getParallelEdges(target, source);
      let parallelEdges = Util.getParallelEdges(source, target);
      let index = parallelEdges.indexOf(item);
      if (source === target) {
        parallelEdges = parallelEdges.filter(parallelEdge => {
          const model = parallelEdge.getModel();
          return model.source === source.id && model.target === target.id;
        });
        index = parallelEdges.indexOf(item);
        return getCirclePath(source, index);
      }
      if (parallelEdgesReverse.length === 0) {
        index--;
      }
      return getParallelPath(source, target, index);
    }
    return Util.pointsToPolygon(points);
  }
});
